package io.geekidea.boot.auth.interceptor;

import com.hwtx.form.domain.meta.FunPermCache;
import com.hwtx.form.util.JacksonUtil;
import io.geekidea.boot.auth.cache.LoginCache;
import io.geekidea.boot.auth.util.LoginUtil;
import io.geekidea.boot.auth.util.TokenUtil;
import io.geekidea.boot.auth.vo.LoginVo;
import io.geekidea.boot.common.constant.CommonConstant;
import io.geekidea.boot.config.properties.LoginAdminProperties;
import io.geekidea.boot.framework.exception.LoginException;
import io.geekidea.boot.framework.exception.LoginTokenException;
import io.geekidea.boot.framework.interceptor.BaseExcludeMethodInterceptor;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.method.HandlerMethod;

import java.util.List;
import java.util.Map;

import static com.hwtx.form.domain.FormConstants.FORM_ID;
import static com.hwtx.form.domain.FormConstants.SHORT_FORM_ID;
import static com.hwtx.form.util.FormUtil.getLoadFormId;

/**
 * @author geekidea
 **/
@Slf4j
public class LoginInterceptor extends BaseExcludeMethodInterceptor {

    private final AntPathMatcher antPathMatcher = new AntPathMatcher();
    @Autowired
    private LoginAdminProperties loginAdminProperties;
    @Resource
    private FunPermCache funPermCache;

    @Override
    protected boolean preHandleMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) {
        // 如果token
        String token = TokenUtil.getToken();
        LoginVo loginVo = null;
        if (StringUtils.isNotBlank(token)) {
            // 获取登录用户信息
            loginVo = LoginUtil.getLoginVo(token);
            if (loginVo != null) {
                // 将管理后台的登录信息保存到当前线程中
                LoginCache.set(loginVo);
            }
        }
        // 判断是否存在@IgnoreLogin，存在，则跳过
        boolean existsIgnoreLoginAnnotation = existsIgnoreLoginAnnotation(handlerMethod);
        if (existsIgnoreLoginAnnotation) {
            return true;
        }
        // 校验登录
        if (StringUtils.isBlank(token)) {
            throw new LoginTokenException("请登录后再操作,requestUrl:" + request.getRequestURL());
        }
        // 校验登录用户信息
        if (loginVo == null) {
            throw new LoginTokenException("登录已过期或登录信息不存在，请重新登录");
        }
        String url = request.getServletPath();
        // 获取登录信息判断
        List<Long> roleIds = loginVo.getRoleIds();
        boolean loginPermission = loginAdminProperties.isLoginPermission();
        List<String> onlyLoginPaths = loginAdminProperties.getOnlyLoginPaths();
        if (CollectionUtils.isNotEmpty(onlyLoginPaths)) {
            boolean isOnlyLoginPath = onlyLoginPaths.stream().anyMatch(path -> antPathMatcher.match(path, url));
            if (isOnlyLoginPath) {
                return true;
            }
        }
        boolean admin = loginVo.isAdmin();
        if (!admin && CollectionUtils.isEmpty(roleIds)) {
            log.error("没有访问权限的登录用户：{}", loginVo);
            throw new LoginException("该角色没有访问权限");
        }
        if (!admin && loginPermission) {
            if (StringUtils.isEmpty(url)) {
                throw new LoginException("当前用户未设置权限");
            }
            if (loginVo.getAdminAuthApi() != null && loginVo.getAdminAuthApi().contains(url)) {
                return true;
            }
            Long formId = getFormId(request, url);
            if (formId != null) {
                if (funPermCache.isNoAuth(formId, url)) {
                    return true;
                }
            } else {
                if (funPermCache.isNoAuth(url)) {
                    return true;
                }
            }
            Map<String, Long> urlAndCode;
            if (formId != null) {
                urlAndCode = loginVo.getFormFunPerms().get(formId);
            } else {
                urlAndCode = loginVo.getUrlFunPerms();
            }
            if (urlAndCode == null) {
                throw new LoginException("当前用户未设置权限");
            }
            if (!urlAndCode.containsKey(url)) {

                log.error("登录用户没有访问权限：{}, url = {}", loginVo, url);
                throw new LoginException("没有访问权限");
            }
        }
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        LoginCache.remove();
    }

    private Long getFormId(HttpServletRequest request, String url) {
        String formId = null;
        Long loadFormId = getLoadFormId(url);
        if (loadFormId != null) {
            return loadFormId;
        }
        if (request.getMethod().equalsIgnoreCase("post")) {
            Object body = request.getAttribute(CommonConstant.REQUEST_PARAM_BODY_STRING);
            if (body != null) {
                Map<String, Object> map = JacksonUtil.json2Map(body.toString());
                if (map.get(SHORT_FORM_ID) != null) {
                    formId = map.get(SHORT_FORM_ID).toString();
                }
                if (formId == null && map.get(FORM_ID) != null) {
                    formId = map.get(FORM_ID).toString();
                }
            }
        } else {
            formId = request.getParameter(SHORT_FORM_ID);
            if (formId == null) {
                formId = request.getParameter(FORM_ID);
            }
        }
        if (formId != null) {
            return Long.valueOf(formId);
        }
        return null;
    }
}
